package com.newcoin.chat.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.newcoin.chat.beans.entity.*;
import com.newcoin.chat.beans.vo.*;
import com.newcoin.chat.dao.GroupDao;
import com.newcoin.chat.service.GroupService;
import com.newcoin.chat.util.QRCodeUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;

@Service
@Slf4j
public class GroupServiceImpl implements GroupService {

    @Autowired
    private GroupDao dao;
    @Value("${host}")
    private String host;
    @Value("${group-qr-code}")
    private String groupQrCode;

    /**
     * 创建群聊
     *
     * @param userId
     * @param userIds
     * @return
     * @throws Exception
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultVo<Object> createGroup(long userId, String userIds, String sign) throws Exception {
        log.info("创建群聊入参 userId={},userIds={},sign={}", userId, userIds, sign);
        ResultVo<Object> resultVo = new ResultVo<>();
        JSONArray users = JSON.parseArray(userIds);
        log.info("users={}", users);
        GroupInfoEntity groupInfoEntity = new GroupInfoEntity();
        groupInfoEntity.setGroupOwner(userId);
        groupInfoEntity.setGroupSign(sign);
        String name = "";
        String groupHeadImgPath = "";
        if (users.size() <= 2) {
            UserEntity userEntity = dao.getNicknameAndHeadImgPathById(userId);
            name = name + userEntity.getNickname();
            groupHeadImgPath = groupHeadImgPath + userEntity.getHeadImgPath();
            for (int i = 0; i < users.size(); i++) {
                UserEntity groupMemberInfo = dao.getNicknameAndHeadImgPathById(Long.parseLong(String.valueOf(users.get(i))));
                name = name + "、" + groupMemberInfo.getNickname();
                groupHeadImgPath = groupHeadImgPath + "," + groupMemberInfo.getHeadImgPath();
            }
        } else {
            UserEntity userEntity = dao.getNicknameAndHeadImgPathById(userId);
            name = userEntity.getNickname() + "创建的群聊";
            groupHeadImgPath = groupHeadImgPath + userEntity.getHeadImgPath();
            for (int i = 0; i < 2; i++) {
                UserEntity groupMemberInfo = dao.getNicknameAndHeadImgPathById(Long.parseLong(String.valueOf(users.get(i))));
                groupHeadImgPath = groupHeadImgPath + "," + groupMemberInfo.getHeadImgPath();
            }
        }
        groupInfoEntity.setGroupName(name);
        groupInfoEntity.setGroupHeadImgPath(groupHeadImgPath);
        log.info("groupInfoEntity={}", groupInfoEntity);
        int row = dao.addGroup(groupInfoEntity);
        if (row != 1)
            throw new RuntimeException("创建群聊失败");
        int row1 = dao.addGroupMember(groupInfoEntity.getId(), userId);
        int index = users.size() <= 5 ? users.size() : 5;
        for (int i = 0; i < index; i++) {
            row1 = row1 + dao.addGroupMember(groupInfoEntity.getId(), Long.parseLong(String.valueOf(users.get(i))));
        }
        log.info("row1={}", row1);
        if (row1 != index + 1) {
            throw new RuntimeException("创建群聊失败");
        }
        if (users.size() > 5) {
            new Thread(() -> {
                int row2 = 0;
                GroupApplicationEntity groupApplicationEntity = new GroupApplicationEntity();
                groupApplicationEntity.setGroupId(groupInfoEntity.getId());
                groupApplicationEntity.setGroupName(groupInfoEntity.getGroupName());
                groupApplicationEntity.setFromUser(userId);
                groupApplicationEntity.setState(0);
                for (int i = 5; i < users.size(); i++) {
                    groupApplicationEntity.setToUser(Long.parseLong(String.valueOf(users.get(i))));
                    row2 = row2 + dao.addGroupInviteMessage(groupApplicationEntity);
                }
                log.info("发送群邀请row2={}", row2);
            }).start();
        }
        new Thread(() -> {
            int row3 = dao.addGroupQRCode(groupInfoEntity.getId(), host + ":23543/static/groupQrCode/" + groupInfoEntity.getId() + ".png");
//            QRCodeUtil.generateQRCodeImage(String.valueOf(groupInfoEntity.getId()), 350, 350, "D:\\static\\groupQrCode\\");
            QRCodeUtil.generateQRCodeImage(String.valueOf(groupInfoEntity.getId()), 350, 350, groupQrCode);
            log.info("添加群二维码 row3={}", row3);
        }).start();
        resultVo.setStatus(200);
        resultVo.setMsg("创建群聊成功");
        resultVo.setResultData(groupInfoEntity.getId());
        log.info("resultVo={}", resultVo);
        return resultVo;
    }

    /**
     * 修改群名称
     *
     * @param userId
     * @param groupId
     * @param name
     * @return
     * @throws Exception
     */
    @Override
    public ResultVo modifyGroupName(long userId, long groupId, String name) throws Exception {
        log.info("修改群名称入参 userId={},groupId={},name={}", userId, groupId, name);
        ResultVo resultVo = new ResultVo();
        if (name == null || name.trim().equalsIgnoreCase("")) {
            resultVo.setStatus(507);//群名不能为空
            resultVo.setMsg("群名不能为空");
            return resultVo;
        }
        GroupInfoEntity groupInfo = dao.getGroupInfoByOwnerAndGroupId(userId, groupId);
        log.info("修改群名称获取群信息groupInfo={}", groupInfo);
        if (groupInfo == null) {
            resultVo.setStatus(401);//群名不能为空
            resultVo.setMsg("您不是群主不可以修改群名称");
            return resultVo;
        }
        groupInfo.setGroupName(name);
        int row = dao.modifyGroupName(groupInfo);
        log.info("row={}", row);
        if (row != 1)
            throw new RuntimeException("修改群名称失败");
        resultVo.setStatus(200);
        resultVo.setMsg("修改群名称成功");
        log.info("resultVo={}", resultVo);
        return resultVo;
    }

    /**
     * 是否有新的群邀请信息
     *
     * @param userId
     * @return
     * @throws Exception
     */
    @Override
    public ResultVo<Boolean> isThereANewGroupApplication(long userId) throws Exception {
        log.info("是否有新的群邀请信息入参 userId={}", userId);
        ResultVo<Boolean> resultVo = new ResultVo<>();
        resultVo.setStatus(200);
        int count = dao.isThereANewGroupApplication(userId);
        if (count > 0)
            resultVo.setResultData(true);
        else
            resultVo.setResultData(false);
        log.info("resultVo={}", resultVo);
        return resultVo;
    }

    /**
     * 获取邀请进群通知最近10条
     *
     * @param userId
     * @return
     * @throws Exception
     */
    @Override
    public ResultVo<List<GroupApplicationEntity>> groupInviteMessages(long userId) throws Exception {
        log.info("获取邀请进群通知入参 userId={}", userId);
        ResultVo<List<GroupApplicationEntity>> resultVo = new ResultVo<>();
        resultVo.setStatus(200);
        List<GroupApplicationEntity> list = dao.getGroupInviteMessages(userId);
        log.info("listCount={}", list.size());
        resultVo.setMsg("查询成功");
        resultVo.setResultData(list);
        new Thread(() -> {
            list.forEach(m -> {
                if (m.getState() == 0)
                    dao.updateGroupApplicationStateById(m.getId(), 1);
            });
        }).start();
        log.info("resultVo={}", resultVo);
        return resultVo;
    }

    /**
     * 获取所有的邀请进群群通知
     *
     * @param userId
     * @param page
     * @return
     * @throws Exception
     */
    @Override
    public ResultVo<GroupApplicationVo> getAllGroupApplicationMessages(long userId, int page) throws Exception {
        log.info("获取所有的邀请进群群通知入参 userId=#{},page={}", userId, page);
        ResultVo<GroupApplicationVo> resultVo = new ResultVo<>();
        page = (page - 1) * 10;
        PageParamVo pageParamVo = new PageParamVo();
        pageParamVo.setPage(page);
        pageParamVo.setUserId(userId);
        log.info("pageParamVo={}", pageParamVo);
        List<GroupApplicationEntity> list = dao.getAllGroupApplicationListById(pageParamVo);
        log.info("listCount={}", list.size());
        int count = dao.getAllGroupApplicationCount(userId);
        log.info("count={}", count);
        GroupApplicationVo friendApplicationVo = new GroupApplicationVo();
        if (count <= 10) {
            friendApplicationVo.setTotalPages(1);
            friendApplicationVo.setCurrentPage(1);
        } else {
            friendApplicationVo.setTotalPages(count % 10 == 0 ? count / 10 : count / 10 + 1);
            friendApplicationVo.setCurrentPage(page / 10 + 1);
        }
        friendApplicationVo.setApplicationList(list);
        log.info("friendApplicationVo={}", friendApplicationVo);
        resultVo.setStatus(200);
        resultVo.setMsg("查询成功");
        resultVo.setResultData(friendApplicationVo);
        log.info("resultVo={}", resultVo);
        return resultVo;
    }

    /**
     * 通过或者拒绝群邀请
     *
     * @param groupApplicationId
     * @param state
     * @return
     * @throws Exception
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultVo<String> passOrRejectGroupApplication(long groupApplicationId, int state) throws Exception {
        log.info("通过或者拒绝群邀请入参 groupApplicationId={},state={}", groupApplicationId, state);
        ResultVo<String> resultVo = new ResultVo<>();
        int row = dao.updateGroupApplicationStateById(groupApplicationId, state);
        log.info("通过后者拒绝好友 更新通知 row={}", row);
        if (row != 1) {
            resultVo.setStatus(507);//通过群邀请失败
            if (state == 2)
                resultVo.setMsg("接受失败");
            else if (state == 3)
                resultVo.setMsg("拒绝失败");
            log.info("resultVo={}", resultVo);
            return resultVo;
        } else {
            if (state == 2) {
                GroupApplicationEntity groupApplicationEntity = dao.getGroupApplicationInfo(groupApplicationId);
                int count = dao.getGroupMemberIsPresence(groupApplicationEntity.getGroupId(), groupApplicationEntity.getToUser());
                if (count >= 1) {
                    resultVo.setStatus(500);
                    resultVo.setMsg("您已在该群组中");
                    return resultVo;
                }
                int row1 = dao.addGroupMember(groupApplicationEntity.getGroupId(), groupApplicationEntity.getToUser());
                log.info("row1={}", row1);
                if (row1 != 1)
                    throw new RuntimeException("通过群邀请失败");
                resultVo.setStatus(200);
                resultVo.setMsg("接受成功");
            } else if (state == 3) {
                resultVo.setStatus(200);
                resultVo.setMsg("拒绝成功");
            }
        }
        log.info("resultVo={}", resultVo);
        return resultVo;
    }

    /**
     * 移出群聊
     *
     * @param userId
     * @param groupId
     * @param groupMemberId
     * @return
     * @throws Exception
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultVo removeUser(long userId, long groupId, long groupMemberId) throws Exception {
        log.info("移出群聊入参userId={},groupId={},groupMemberId={}", userId, groupId, groupMemberId);
        ResultVo resultVo = new ResultVo();
        GroupInfoEntity groupInfoEntity = dao.getGroupInfoByOwnerAndGroupId(userId, groupId);
        log.info("groupInfoEntity={}", groupInfoEntity);
        if (groupInfoEntity == null) {
            resultVo.setStatus(401);//没有权限移除群成员
            resultVo.setMsg("您没有权限移除群成员");
            return resultVo;
        }
        int row = dao.removeGroupMember(groupMemberId, groupId);
        if (row != 1)
            throw new RuntimeException("移除群成员失败");
        resultVo.setStatus(200);
        resultVo.setMsg("移除群成员成功");
        log.info("resultVo={}", resultVo);
        return resultVo;
    }

    /**
     * 群成员退出群聊
     *
     * @param userId
     * @param groupId
     * @return
     * @throws Exception
     */
    @Override
    public ResultVo dropOutGroup(long userId, long groupId) throws Exception {
        log.info("群成员退出群聊入参 userId={},groupId={}", userId, groupId);
        ResultVo resultVo = new ResultVo();
        int row = dao.removeGroupMember(userId, groupId);
        if (row != 1)
            throw new RuntimeException("退出群聊失败");
        resultVo.setStatus(200);
        resultVo.setMsg("退出群聊成功");
        log.info("resultVo={}", resultVo);
        return resultVo;
    }

    /**
     * 邀请好友进群（可以是群主  也可以是群成员）
     *
     * @param userId
     * @param friendId
     * @param groupId
     * @return
     * @throws Exception
     */
    @Override
    public ResultVo inviteFriendAddGroup(long userId, long friendId, long groupId) throws Exception {
        log.info("邀请好友进群入参userId={},friendId={},groupId={}", userId, friendId, groupId);
        ResultVo resultVo = new ResultVo();
        GroupInfoEntity groupInfo = dao.getGroupInfoByGroupId(groupId);
        if (groupInfo == null) {
            resultVo.setStatus(407);//无群信息
            resultVo.setMsg("没有获取到相关的群信息");
            log.info("resultVo={}", resultVo);
            return resultVo;
        }
        GroupApplicationEntity groupApplicationEntity = new GroupApplicationEntity();
        groupApplicationEntity.setFromUser(userId);
        groupApplicationEntity.setGroupId(groupId);
        groupApplicationEntity.setGroupName(groupInfo.getGroupName());
        groupApplicationEntity.setState(0);
        groupApplicationEntity.setToUser(friendId);
        int row = dao.addGroupInviteMessage(groupApplicationEntity);
        if (row != 1) {
            resultVo.setStatus(507);
            resultVo.setMsg("邀请好友失败");
            log.info("resultVo={}", resultVo);
            return resultVo;
        }
        resultVo.setStatus(200);
        resultVo.setMsg("邀请好友成功");
        log.info("resultVo={}", resultVo);
        return resultVo;
    }

    /**
     * 群主打开或关闭阅后即焚
     *
     * @param userId
     * @param state
     * @return
     * @throws Exception
     */
    @Override
    public ResultVo openOrCloseAfterReadingIncineration(long userId, long groupId, int state) throws Exception {
        log.info("群主打开或关闭阅后即焚入参userId={},groupId={},state={}", userId, groupId, state);
        ResultVo resultVo = new ResultVo();
        GroupInfoEntity groupInfo = dao.getGroupInfoByOwnerAndGroupId(userId, groupId);
        log.info("群主打开或关闭阅后即焚 获取群信息groupInfo={}", groupInfo);
        if (groupInfo == null) {
            resultVo.setStatus(401);//无权限设置阅后即焚
            resultVo.setMsg("只有群主才能开启或关闭阅后即焚");
            log.info("resultVo={}", resultVo);
            return resultVo;
        }
        int row = dao.updateGroupState(groupId, state);
        log.info("row={}", row);
        if (row != 1) {
            resultVo.setStatus(507);//群主打开或关闭阅后即焚失败
            resultVo.setMsg(state == 0 ? "关闭阅后即焚失败" : "开启阅后即焚失败");
            log.info("resultVo={}", resultVo);
            return resultVo;
        }
        GroupMsgEntity groupMsgEntity = new GroupMsgEntity();
        groupMsgEntity.setFromUser(userId);
        groupMsgEntity.setGroupId(groupId);
        groupMsgEntity.setContent(burnAfterReadingStatusSwitch(state));
        groupMsgEntity.setIsSystemType(1);
        groupMsgEntity.setState(0);
        groupMsgEntity.setType("text");
        log.info("groupMsgEntity={}", groupMsgEntity);
        int row1 = dao.addGroupSystemMessage(groupMsgEntity);
        log.info("row1={}", row1);
        if (row1 != 1)
            throw new RuntimeException("群主打开或关闭阅后即焚失败");
        resultVo.setStatus(200);
        resultVo.setMsg(state == 0 ? "关闭阅后即焚成功" : "开启阅后即焚成功");
        log.info("resultVo={}", resultVo);
        return resultVo;
    }

    /**
     * 根据群id获取群信息
     *
     * @param groupId
     * @return
     * @throws Exception
     */
    @Override
    public ResultVo<GroupInfoVo> getGroupInfoByGroupId(long groupId) throws Exception {
        log.info("根据群id获取群信息入参groupId={}", groupId);
        ResultVo<GroupInfoVo> resultVo = new ResultVo<>();
        GroupInfoVo groupInfoVo = dao.getGroupInfoVoByGroupId(groupId);
        log.info("groupInfoVo={}", groupInfoVo);
        resultVo.setStatus(200);
        resultVo.setMsg("查询成功");
        resultVo.setResultData(groupInfoVo);
        log.info("resultVo={}", resultVo);
        return resultVo;
    }

    /**
     * 获取群成员
     *
     * @param groupId
     * @return
     * @throws Exception
     */
    @Override
    public ResultVo<List<UserVo>> getGroupMember(long groupId) throws Exception {
        log.info("获取群成员 入参groupId={}", groupId);
        List<UserVo> list = dao.getGroupMember(groupId);
        log.info("list={}", list);
        ResultVo<List<UserVo>> resultVo = new ResultVo<>();
        resultVo.setResultData(list);
        resultVo.setStatus(200);
        resultVo.setMsg("成功");
        log.info("resultVo={}", resultVo);
        return resultVo;
    }

    /**
     * 获取与朋友的阅后即焚状态
     *
     * @param groupId
     * @return
     */
    @Override
    public ResultVo<Integer> getAfterReadingIncinerationState(long groupId) throws Exception {
        log.info("获取与朋友的阅后即焚状态 groupId={}", groupId);
        Integer state = dao.getAfterReadingIncinerationState(groupId);
        ResultVo<Integer> resultVo = new ResultVo();
        resultVo.setMsg("成功");
        resultVo.setStatus(200);
        resultVo.setResultData(state);
        return resultVo;
    }

    /**
     * 获取群组的离线消息
     *
     * @param userId
     * @param groupId
     * @return
     * @throws Exception
     */
    @Override
    public ResultVo<List<GroupOfflineMsgVo>> getOfflineMessage(Long userId, Long groupId) throws Exception {
        log.info("获取群组离线消息入参 userId={},groupId={}", userId, groupId);
        Long recordLastMsgId = dao.getGroupIdOfflineMsg(userId, groupId);
        Long groupLastMsgId = dao.getGroupLastMsgIdByGroupId(groupId);
        List<GroupOfflineMsgVo> list = null;
        if (groupLastMsgId.compareTo(recordLastMsgId) > 0) {
            list = dao.getGroupIdOfflineMsgVo(recordLastMsgId, groupId);
        }
        ResultVo<List<GroupOfflineMsgVo>> resultVo = new ResultVo<>();
        resultVo.setStatus(200);
        resultVo.setMsg("成功");
        resultVo.setResultData(list);
        new Thread(() -> {
            try {
                dao.updateOfflineMsg(userId, groupId);
            } catch (Exception e) {
                log.error("获取离线更改状态报错 e={}", e.getMessage());
            }
        }).start();
        return resultVo;
    }

    /**
     * 修改群名
     *
     * @param groupId
     * @param groupName
     * @return
     * @throws Exception
     */
    @Override
    public ResultVo updateGroupName(Long groupId, String groupName) throws Exception {
        log.info("修改群名入参 groupId={},groupName={}", groupId, groupName);
        ResultVo resultVo = new ResultVo();
        int row = dao.updateGroupName(groupId, groupName);
        if (row != 1) {
            resultVo.setStatus(500);
            resultVo.setMsg("修改群名失败");
            return resultVo;
        }
        resultVo.setStatus(200);
        resultVo.setMsg("成功");
        return resultVo;
    }

    /***
     * 获取用户的所有的群
     * @param userId
     * @return
     * @throws Exception
     */
    @Override
    public void getGroupMemberByUserId(Long userId) throws Exception {
        log.info("获取用户的所有的群入参={}", userId);
        List<GroupMemberEntity> list = dao.getGroupMemberByUserId(userId);
        log.info("list={}", list);
        for (GroupMemberEntity groupMemberEntity : list) {
            log.info("groupMemberEntity={}", groupMemberEntity);
            Long groupLastMsgId = dao.getGroupLastMsgIdByGroupId(groupMemberEntity.getGroupId());
            log.info("groupLastMsgId={}", groupLastMsgId);
            int row = dao.updateUserGroupLastMsgId(groupMemberEntity.getId(), groupLastMsgId);
            log.info("row={}", row);
            if (row != 1) {
                dao.updateUserGroupLastMsgId(groupMemberEntity.getId(), groupLastMsgId);
            }
        }
    }


    /**
     * 阅后即焚状态选择器
     *
     * @param state
     * @return
     */
    private String burnAfterReadingStatusSwitch(int state) {
        switch (state) {
            case 0:
                return "关闭阅后即焚";
            case 1:
                return "开启阅后即焚";
            case 2:
                return "开启10秒后焚毁";
            case 3:
                return "开启5分钟后焚毁";
            case 4:
                return "开启1小时后后焚毁";
            case 5:
                return "开启24小时后焚毁";
            default:
                return "关闭阅后即焚";
        }
    }


}
